#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cassert>
#include <fstream>
#include "../Common/Log.hpp"
#include "../Common/Util.hpp"
namespace ns_model
{
    using namespace FileTool;
    static const std::string DefaultQuestionlistPath = "./questions/question.list";
    static const std::string DefaultSpecifiedQuestionPath = "./questions/";

    struct Question
    {
        std::string _id;     // 题目编号
        std::string _title;  // 题目标题
        std::string _level;  // 难度
        int _cpu_limit;      // 运行时间限制
        int _mem_limit;      // 内存限制
        std::string _desc;   // 题目描述
        std::string _header; // 核心代码
        std::string _tail;   // 题目测试用例
    };
    class Model
    {
    private:
        std::unordered_map<std::string, Question> _model_Map;

    public:
        Model()
        {
            LoadTileConfFile(DefaultQuestionlistPath);
        }
        bool LoadTileConfFile(const std::string &questionlist)
        {
            std::ifstream rd(questionlist.c_str());
            if (!rd.is_open())
            {
                LOG(FATAL, "open question.list error!\n");
                return false;
            }
            std::string line;
            int lines = 0;
            while (std::getline(rd, line))
            {
                ++lines;
                std::vector<std::string> res;
                FileTool::StringUtil::SepString(line, &res," ");
                if (res.size() != 5)
                {
                    LOG(WARNING, "读取配置文件%d行出错", lines);
                    continue;
                }
                Question q;
                q._id = res[0];
                q._title = res[1];
                q._level = res[2];
                q._cpu_limit = std::stoi(res[3]);
                q._mem_limit = std::stoi(res[4]);

                std::string path = DefaultSpecifiedQuestionPath;
                path += q._id; // ./questions/1/
                path += "/";
                if (!FileTool::RWFile::ReadDataToFile(path + "desc.txt", &(q._desc), true))
                {
                    LOG(WARNING, "读取第%s题的%s文件出错!\n", q._id.c_str(), (path + "desc.txt").c_str());
                    continue;
                }
                if (!FileTool::RWFile::ReadDataToFile(path + "header.cpp", &(q._header), true))
                {
                    LOG(WARNING, "读取第%s题的%s文件出错!\n", q._id.c_str(), (path + "header.cpp").c_str());
                    continue;
                }
                if (!FileTool::RWFile::ReadDataToFile(path + "tail.cpp", &(q._tail), true))
                {
                    LOG(WARNING, "读取第%s题的%s文件出错!\n", q._id.c_str(), (path + "tail.cpp").c_str());
                    continue;
                }
                _model_Map.insert({q._id,q});
            }
            LOG(INFO, "load tiles done!,lines = %d\n",lines);
            rd.close();
            return true;
        }
        bool GetAllQuestionList(std::vector<Question> *out)
        {
            if (_model_Map.size() == 0)
            {
                LOG(FATAL,"题目为空!\n");
                return false;
            }
            for (auto &[x, y] : _model_Map)
            {
                out->push_back(y);
            }
            //排序
            std::sort(out->begin(),out->end(),[&](const Question& px,const Question& py)
            {
                return px._id < py._id ;
            });
            return true;
        }
        bool GetOnceQuestion(const std::string &number, Question *q)
        {
            const auto &iter = _model_Map.find(number);
            if (iter == _model_Map.end())
            {
                return false;
            }
            *q = iter->second;
            return true;
        }
        ~Model()
        {
        }
    };
};
